package com.ms.service.module.account;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.xpec.c4.db.dto.DTManualTransfer;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.service.group.datalayer.IShareGroupData;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;

/**
 * 帐户信息
 * 
 * @author lipeilin
 * @2011-5-10 下午03:32:32
 * 
 */
public class Account implements IShareGroupData {

	//private static final Log log = LogFactory.getLog(Account.class);
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -2376586616178875733L;
	
	/**
	 * 預設立即玩編號 (非立即玩帳號用的編號)
	 */
	public static final int NORMAL_PLAYER_TRIAL_NUMBER = 0;
	
	/**
	 * 綁定裝置的立即玩帳號固定用的編號
	 */
	public static final int DEVICE_TRIAL_PLAYER_NUMBER = -1;
	
	/**
	 * 立即玩編號
	 * 
	 * @see com.ms.service.module.account.db.AccountModel#getTrialNumber()
	 */
	private int trialNumber = 0;

	/**
	 * 帐户
	 */
	@DTManualTransfer
	//UUID先不支援 Utility的copy , 原寫法沒檢查type, 會強迫給職結果爛掉,與其讓她每次檢查class type不如先標記
	private GUID accountId;

	/**
	 * 是否在线
	 */
	private boolean online; 
	
	/**
	 * 現金點數
	 */
	private long cash;
	
	/**
	 * 紅利點數
	 */
	private BigDecimal bonus;
	
	/**
	 * 銀行密碼
	 */
	private String bankPassword;
	
	/**
	 * 上次读取时间（每次从Manager读取时，修改为当前时间）
	 */
	private long loadTime;
	
	/**
	 * 锁
	 */
	private transient Object lock;

	/**
	 * 角色列表
	 */
	@DTManualTransfer
	//UUID先不支援 Utility的copy , 原寫法沒檢查type, 會強迫給職結果爛掉,與其讓她每次檢查class type不如先標記
	private ArrayList<GUID> players = new ArrayList<GUID>();
	
	/**
	 * 營運商accountID
	 */
	private String cooperatorAccountId;

	/**
	 * gm權利 (不受人數影響可登入)
	 */
	private int gmPower;
	
	//ipv4 address
	private String clientAddress;
	
	/**
	 * 已創角數目
	 */
	private int createdPlayerCount;
	
	/**
	 * 角色Guid及對應編號
	 * 砍掉的角色會從此處移除，萬一又移回來就順號接下去吧
	 */
	@DTManualTransfer
	//UUID先不支援 Utility的copy
	private Map<GUID, Integer> playerSerialNumMap = new HashMap<GUID, Integer>();

	/**
	 * 上線的邀請碼
	 */
	private String uplineCode;

	/**
	 * 活動代碼，透過營運商特定網址登入時會帶入的代碼
	 */
	private String cooperatorEventCode;

	/**
	 * 綁定手機號碼
	 */
	private String bindPhone;

	/**
	 * 綁定信箱
	 */
	private String bindMail;
	
	/*
	 * 認證時間 
	 */
	private Calendar registerTime;
	
	/**
	 * 創建帳號的平台
	 */
	private String registeredPlatform;
	
	/**
	 * 是否已經有首次轉點角色 
	 */
	private boolean haveFirstStoreCharacter;
	
	/**
	 * 玩家被GMTOOL禁止登入時間
	 */
	private long loginBanTime;
	
	/**
	 * 上次鎖定的角色GUID
	 */
	private String lastLockPlayerGUID;
	
	/**
	 * deviceToken,有效時間(秒)
	 */
	private String deviceToken;
	
	/**
	 * 邀請碼錯誤次數
	 */
	private int inviteCodeErrorCount;
	
	/**
	 * 邀請碼錯誤次數到達上限，解鎖時間
	 */
	private Date inviteCodeUnlockTime;

	/**
	 * 該帳號對應的deviceID
	 */
	private String deviceID;

	/**
	 * 營運商 id
	 */
	private String venderId;
	
	/**
	 * 子營運商 id
	 */
	private String subVenderId;

	/**
	 * 產生 coop id
	 * 
	 * @param ezname
	 * @param openId
	 * @return
	 */
	public static String makeCoopId(String ezname, String openId) {
		return ezname + "_" + openId;
	}

	public boolean isOnline() {
		return online;
	}

	public long getLoadTime() {
		return loadTime;
	}

	public void setLoadTime(long loadTime) {
		this.loadTime = loadTime;
	}
	
	public Account(){
		lock = new Object();
		trialNumber = NORMAL_PLAYER_TRIAL_NUMBER;
	}
	
	/**
	 * 上线
	 * 
	 * @return 是否可以成功上线
	 */
	public boolean online() {
		synchronized (lock) {
			if (!online) {
				online = true;
				return true;
			}
			return false;
		}
	}

	/**
	 * 下线
	 */
	public void offline() {
		synchronized (lock) {
			online = false;
		}
	}

	public ArrayList<GUID> getPlayers() {
		return players;
	}

	public void setPlayers(ArrayList<GUID> players) {
		this.players = players;
	}

	public GUID getAccountId() {
		return accountId;
	}

	public void setAccountId(GUID accountId) {
		this.accountId = accountId;
	}

	@Override
	public String toString() {
		return accountId + " | " + players;
	}
	
	/**
	 * 取得目前player list內所擁有的實際玩家數量
	 * @return
	 */
	public int getPlayerCount(){
		int count = 0;
		for (GUID playerid : this.players) {
			if( playerid != null){
				count ++;
			}
		}
		return count;
	}
	/**
	 * 新增一個玩家至最近的空格格內
	 * @param player
	 */
	public void addPlayer(GUID player){
		boolean get = false;
		for(int i =0; i < this.players.size(); i++){
			if( this.players.get(i) == null){
				 this.players.set(i, player);
				 get = true;
				 break;
			}
		}
		if(! get){
			this.players.add(player);
		}
		
		//記錄創角數及對應的角色guid
		playerSerialNumMap.put(player, ++createdPlayerCount);
		
	}
	/**
	 * 刪除某個玩家的欄位
	 * @param player
	 * @return
	 */
	public boolean removePLayer(GUID player){
		int index = this.players.indexOf(player);
		if(index == -1 ){
			return false;
		}
		if(index == this.players.size() -1){
			this.players.remove(index);
			index--;
			while((index >= 0) && (players.get(index) == null)){	
				this.players.remove(index);
				index --;
			}
		}
		
		else{
			this.players.set(index, null);
		}
		if(getPlayerCount() == 0)
			this.players.clear();
		
		//移除對應號碼
		playerSerialNumMap.remove(player);
		
		 return true;
	}
	/**
	 * 後門登入用,取得第一個帳號
	 * @return
	 */
	public GUID getFirstPlayer(){
		for (GUID playerid : this.players) {
			if( playerid != null){
				return playerid;
			}
		}
		return null;
	}

	static class FirstPlayerActiveZone
	{
		public String zoneId;
		public GUID playerId;
		public FirstPlayerActiveZone(String zoneId, GUID playerId) {
			super();
			this.zoneId = zoneId;
			this.playerId = playerId;
		}		
	}
	
	private  FirstPlayerActiveZone FindFirstPlayerActiveZone(ArrayList<GUID> players) {

		for(GUID playerId : players)
		{
			String zoneId= PlayerCommonInfoManager.getInstance()
							.getPlayerZoneId(playerId);
			
			if(zoneId != null)
			{
				return new FirstPlayerActiveZone(zoneId,playerId);
			}
		}
		return null;
	}
	
	public String getClientAddress() {
		return clientAddress;
	}

	public void setClientAddress(String clientAddress) {
		this.clientAddress = clientAddress;
	}

	public int getGmPower()
    {
	    return gmPower;
    }

	public void setGmPower(int gmPower)
    {
	    this.gmPower = gmPower;
    }
	
	public int getCreatedPlayerCount()
    {
	    return createdPlayerCount;
    }

	public void setCreatedPlayerCount(int createdPlayerCount)
    {
	    this.createdPlayerCount = createdPlayerCount;
    }
	
	public Map<GUID, Integer> getPlayerSerialNumMap()
    {
	    return playerSerialNumMap;
    }

	public void setPlayerSerialNumMap(Map<GUID, Integer> playerSerialNumMap)
    {
	    this.playerSerialNumMap = playerSerialNumMap;
    }

	public String getCooperatorAccountId() {
		return cooperatorAccountId;
	}

	public void setCooperatorAccountId(String cooperatorAccountId) {
		this.cooperatorAccountId = cooperatorAccountId;
	}

	/**
	 * 檢查帳號是否為立即玩帳號
	 * 
	 * @return true 是, false 不是
	 */
	public boolean isTrialAccount() {
		if (!cooperatorAccountId.startsWith(AccountModule.TRIAL_ACCOUNT_NAME) &&
		    !cooperatorAccountId.startsWith(AccountModule.TRIAL_DEVICE_ACCOUNT_NAME)) {
			return false;
		}

		if (trialNumber == NORMAL_PLAYER_TRIAL_NUMBER) {
			return false;
		}

		return true;
	}

	public int getTrialNumber() {
		return trialNumber;
	}

	public void setTrialNumber(int trialNumber) {
		this.trialNumber = trialNumber;
	}

	public long getCash() {
		return cash;
	}

	public void setCash(long cash) {
		this.cash = cash;
	}
	
	public BigDecimal getBonus() {
		return bonus;
	}

	public void setBonus(BigDecimal bonus) {
		this.bonus = bonus;
	}


	public String getBankPassword() {
		return bankPassword;
	}

	public void setBankPassword(String bankPassword) {
		this.bankPassword = bankPassword;
	}
	

	public String getUplineCode() {
		return uplineCode;
	}

	public void setUplineCode(String uplineCode) {
		this.uplineCode = uplineCode;
	}

	public String getCooperatorEventCode() {
		return cooperatorEventCode;
	}

	public void setCooperatorEventCode(String cooperatorEventCode) {
		this.cooperatorEventCode = cooperatorEventCode;
	}

	public String getBindPhone() {
		return bindPhone;
	}

	public void setBindPhone(String bindPhone) {
		this.bindPhone = bindPhone;
	}

	public String getBindMail() {
		return bindMail;
	}

	public void setBindMail(String bindMail) {
		this.bindMail = bindMail;
	}
	
	public Calendar getRegisterTime() {
		return registerTime;
	}

	public void setRegisterTime(Calendar registerTime) {
		this.registerTime = registerTime;
	}

	/**
	 * 是否有綁信箱
	 * 
	 * @return
	 */
	public boolean isHaveBindMail() {
		if (GameUtility.isHaveString(bindMail)) {
			return true;
		}

		return false;
	}

	/**
	 * 是否有綁手機
	 * 
	 * @return
	 */
	public boolean isHaveBindPhone() {
		if (GameUtility.isHaveString(bindPhone)) {
			return true;
		}

		return false;
	}

	/**
	 * 是否為認證會員
	 * 
	 * @return 是: true<br>
	 *         否: false
	 */
	public boolean isVerifiedMember() {
		
		//20160825 Sean 
		//後來確認只有手機認證過的才算是認證玩家
//		if (isHaveBindMail()) {
//			return true;
//		}

//		if (isHaveBindPhone()) {
//			return true;
//		}
//
//		return false;
		
		//20171129調整成依照設定檔的方式判斷認證
		return AccountVerifyCheckWay.isVerifyAccount(this);
	}

	public boolean isHaveFirstStoreCharacter() {
		return haveFirstStoreCharacter;
	}

	public void setHaveFirstStoreCharacter(boolean haveFirstStoreCharacter) {
		this.haveFirstStoreCharacter = haveFirstStoreCharacter;
	}
	
	public long getLoginBanTime() {
		return loginBanTime;
	}

	public void setLoginBanTime(long loginBanTime) {
		this.loginBanTime = loginBanTime;
	}

	public String getRegisteredPlatform() {
		return registeredPlatform;
	}

	public void setRegisteredPlatform(String registeredPlatform) {
		this.registeredPlatform = registeredPlatform;
	}

	public String getLastLockPlayerGUID() {
		return lastLockPlayerGUID;
	}

	public void setLastLockPlayerGUID(String lastLockPlayerGUID) {
		this.lastLockPlayerGUID = lastLockPlayerGUID;
	}

	public String getDeviceToken() {
		return deviceToken;
	}

	public void setDeviceToken(String deviceToken) {
		this.deviceToken = deviceToken;
	}

	public int getInviteCodeErrorCount() {
		return inviteCodeErrorCount;
	}

	public void setInviteCodeErrorCount(int inviteCodeErrorCount) {
		this.inviteCodeErrorCount = inviteCodeErrorCount;
	}

	public Date getInviteCodeUnlockTime() {
		return inviteCodeUnlockTime;
	}

	public void setInviteCodeUnlockTime(Date inviteCodeUnlockTime) {
		this.inviteCodeUnlockTime = inviteCodeUnlockTime;
	}
	
	/** 解鎖時間 秒**/
	public int getInviteCodeUnlockTimeSec(){
		if(inviteCodeUnlockTime == null){
			return 0;
		}
		return ((Long)(inviteCodeUnlockTime.getTime() / 1000)).intValue();
	}

	/**
	 * 是否為機器人帳號
	 * 
	 * @return
	 */
	public boolean isRobot() {
		return Account.isRobotAccount(cooperatorAccountId);
	}

	/**
	 * 檢查指定的 cooperatorAccountId 是不是機器人的帳號
	 * 
	 * @param cooperatorAccountId
	 * @return
	 */
	public static boolean isRobotAccount(String cooperatorAccountId) {
		if(!GameUtility.isHaveString(cooperatorAccountId)){
			return false;
		}
		
		return false;
	}

	public String getDeviceID() {
		return deviceID;
	}

	public void setDeviceID(String deviceID) {
		this.deviceID = deviceID;
	}

	public String getVenderId() {
		return venderId;
	}

	public void setVenderId(String venderId) {
		this.venderId = venderId;
	}

	public String getSubVenderId() {
		return subVenderId;
	}

	public void setSubVenderId(String subVenderId) {
		this.subVenderId = subVenderId;
	}
}
